#ifndef NXR_SENSOR_TYPES_H
#define NXR_SENSOR_TYPES_H

#include <vector>
#include <string>
#include <map>

namespace nxr_client{

    enum HelperTrackingMode {
        TRACKING_NONE = -1,
        TRACKING_3DOF,
        TRACKING_6DOF,
        TRACKING_SLAM,
    };

    struct NxrSharedData{
        float rotation[4];
        float translation[3];
        float prediction_coff_s[3];
        float prediction_coff_b[3];
        float prediction_coff_bdt[3];
        float prediction_coff_bdt2[3];
        long long int dataFetchTimeMs;
        long long int dataTimeStampMs;
        int source;//0->raw, 1->qvr
        int black;
        int rotateY;
    };

    struct NxrStreamData{
        unsigned char data[4096000];
        unsigned char left[2048000];
        unsigned char right[2048000];
        uint16_t type;
        uint16_t format;
        uint16_t width;
        uint16_t height;
        uint32_t size;
        uint32_t leftSize;
        uint32_t rightSize;
        uint64_t timestamp;
    };

    struct NxrHidData{
        unsigned char data[8888];
        int length;
        int type;//1=write,2=read
    };

    struct NxrRawData {
        float acc[3];
        float gyro[3];
        float mag[3];
        uint64_t dataTimeStamp;
        int quality;//acc quality
        float temperature;
        uint64_t realTimeStamp;
    };

    struct MagParamter {
        float offset[3] = {0.0, 0.0, 0.0};
        float scale[3] = {0.0, 0.0, 0.0};
        int64_t magTime = 0;
    };

    struct SLIPData {
        std::string version;
        std::string deviceId;
        int length;
        long timestamp;
        int number;
        int responseType;
        int businessNum;
        int businessLen;
        int businessCode;
        int responseCode;
        int status[4] = {-1, -1, -1, -1};
        int lpStatus = 0;
        bool isVerified;
        float lightDegreeValue = 0.0f;
        int videoMode = 0;
        // 地磁参数
        MagParamter magParamter;
    };

    enum Feature {
        FEATURE_NONE = 0,
        FEATURE_VIO,
        FEATURE_CSLAM,
        FEATURE_MAPSHARE,
        FEATURE_RGB,
        FEATURE_TOF,
        FEATURE_FISHEYE,
        FEATURE_EYETRACKING,
        FEATURE_AEC,
        FEATURE_LED,
        FEATURE_LIGHT,
        FEATURE_AUDIO,
        FEATURE_PLANE,
    };

    enum StreamType {
        STREAM_NONE = 0,
        STREAM_EYETRACKING,
        STREAM_RGB,
        STREAM_TOF,
        STREAM_FISHEYE,
        STREAM_THERMAL,
        STREAM_SGBM,
    };

    struct NxrSlamData {
        float data[32];
        int length;
        long long int dataTimeStampMs;
        int source;
    };

    struct pointV2 {
        unsigned short x;
        unsigned short y;
        short data[16];
    };

    struct NxrStreamV2{
        unsigned char *data;
        unsigned char *left;
        unsigned char *right;
        pointV2 *leftData;
        pointV2 *rightData;
        uint16_t type;
        uint16_t format;
        uint16_t width;
        uint16_t height;
        uint32_t size;
        uint32_t leftSize;
        uint32_t rightSize;
        uint64_t timestamp;
        uint32_t leftDataSize;
        uint32_t rightDataSize;
        long long int frameNumber;
    };

    
    struct NxrStream {
        unsigned char *data;
        unsigned char *left;
        unsigned char *right;
        uint16_t type;
        uint16_t format;
        uint16_t width;
        uint16_t height;
        uint32_t size;
        uint32_t leftSize;
        uint32_t rightSize;
        uint64_t timestamp;
    };

    struct point {
        double x;
        double y;
        double z;
    };

    struct NxrPlaneData{
        long long hostTimestamp = 0; //!<Timestamp in µs read on host
        long long deviceTimestamp = 0; //!<Timestamp in µs read on the device
        point points[51200];
        point normal;
        int size;
        int id = -1;
    };

    struct NxrDisplayCalibration {
        float K[2][11];
        float rotation[2][9];
        float translation[2][3];
    };

    struct FishEyeCalibration {
        double K[2][7];
        double rotation[2][9];
        double translation[2][3];
    };

    struct FishEyeSeucmCalibration {
        double K[2][10];
        double rotation[2][9];
        double translation[2][3];
    };

    struct FishEyePDMCalibration {
        double K[2][11];
        double rotation[2][9];
        double translation[2][3];
    };

    struct TOFCalibration{
        double K[11];
        double rotation[9];
        double translation[3];
    };

    struct RGBCalibration{
        double K[3][11];
        double rotation[9];
        double translation[3];
    };

    struct Descriptor {
        std::string type;
        std::vector<std::string> classes;
        double threshold = 0.5;
        bool flipStereo = false;
        bool flipRgb = false;
        bool flipTof = false;
    };

    struct Point{
        float x;
        float y;
        float z;
    };

    struct NxrSkeleton{
        int size;
        Point joints[2][21];
        long long int dataFetchTimeMs;
        long long int dataTimeStampMs;
    };

    struct NxrGesture{
        int size;
        int gesture[2];
        float distance;
        float confidence;
        Point position[2];
        Point slamPosition[2];
        long long int dataFetchTimeMs;
        long long int dataTimeStampMs;
    };

    struct NxrTrackingData {
        float rotation[4];
        float translation[3];
        float prediction_coff_s[3];
        float prediction_coff_b[3];
        float prediction_coff_bdt[3];
        float prediction_coff_bdt2[3];
        long long int dataFetchTimeMs;
        long long int dataTimeStampMs;
        int source;//HELPER_SENSOR_TYPE
    };

    struct NxrTagDetector{
        int id;
        NxrTrackingData data;
    };

    struct NxrPointCloud {
        long long int dataFetchTimeMs;
        long long int dataTimeStampMs;
        std::vector<Point> points;
    };

     struct NxrMicData {
        long long int dataFetchTimeMs;
        long long int dataTimeStampMs;
        unsigned char *data;
        unsigned int dataSize;
    };

    struct NxrExpSetting {
        std::uint32_t iso_value;
        std::uint32_t exp_abs;
        std::uint8_t exp_mode;
        std::int8_t exp_level;
        std::uint8_t exp_anti;    // ANTIBANDING_MODES
        std::uint8_t iso_mode;
    };

/**
 * @brief AWB settings.
 */
    struct NxrAwbSetting {
        std::uint8_t awb_mode;
        std::uint8_t awb_lock;
    };

/**
 * @brief AF settings.
 */
    struct NxrAfSetting {
        std::uint8_t af_mode;
        std::uint8_t af_dist;
    };

/**
 * @brief Device setting.
 */
    struct NxrDeviceSetting {
        std::uint32_t cmd;   //sensorId:8 + channel:8 + sensorCmd:16

        union {
            std::uint8_t val[24];
            NxrAwbSetting awb;
            NxrExpSetting exp;
            NxrAfSetting af;
            std::int16_t val16;
            std::int32_t val32;
        } args;
    };

    struct NxrVersion {
        int major = 0; //!< Major number of the version
        int minor = 0; //!< Minor number of the version
        int patch = 0; //!< Patch number of the version
    };

    enum PlaneType {
        NONE = 0,
        TOF,
        STEREO,
    };

    struct NxrCnnRawData{
        float *data;
        unsigned int size;
    };

    struct NxrCnnObject {
        int shape = 0;
        int typeID = -1;
        std::string type = "";
        double x = 0;
        double y = 0;
        double width = 0;
        double height = 0;
        double confidence = 0;
        int size =0;
        point *keypoints;
    };

    struct Float3{
        float v0;
        float v1;
        float v2;
    };

    struct Float2{
        float v0;
        float v1;
    };

    struct Int3{
        uint32_t v0;
        uint32_t v1;
        uint32_t v2;
    };

    struct NxrSurface {
        int32_t version;
        uint64_t id;

        uint32_t verticesSize;

        Float3 *vertices;
        Float3 *vertexNormals;

        uint32_t trianglesSize;
        Int3 *triangles;

        Float2 *textureCoordinates;

        uint32_t textureWidth;
        uint32_t textureHeight;
        uint8_t *textureRgba;
    };

    struct NxrSurfaceMap{
        uint64_t key;
        NxrSurface surface;
    };

    typedef union ETPoint2D {
        struct {
            float x, y;
        };
        float seq[2];
    };

    typedef union ETPoint3D {
        struct {
            float x, y, z;
        };
        float seq[3];
    };

    struct ETGazePoint {
        unsigned int gazeBitMask;//!<gaze bit mask, identify the six data below are valid or invalid.
        ETPoint3D gazePoint;//!<gaze point, x and y are valid, z default value is 0, x and y scope are related to the input calibration point, not fixed.
        ETPoint3D rawPoint;//!<gaze point before smooth, x and y are valid, z default value is 0, x and y scope are as above.
        ETPoint3D smoothPoint;//!<gaze point after smooth, x and y are valid, z default value is 0, x and y scope are as above.
        ETPoint3D gazeOrigin;//!<origin gaze center coordinate.
        ETPoint3D gazeDirection;//!<gaze direction.
        float re;//!<gaze re value, confidence level.
        unsigned int exDataBitMask;//!<reserved data.
        float exData[32];//!<reserved data.
    };

    struct ETPupilInfo {
        unsigned int pupilBitMask;//!<pupil bit mask, identify the six data below are valid or invalid.
        ETPoint2D pupilCenter;//!<pupil center(0-1), the coordinate value of pupil center in the image, normalization value, image height and width is 1.
        float pupilDistance;//!<the distance between pupil and camera(mm)
        float pupilDiameter;//!<pupil diameter, pupil long axis value(0-1), the ratio of the pixel value of the long axis size of the pupil ellipse to the image width, normalization value.
        float pupilDiameterMM;//!<pupil diameter, pupil long axis value(mm).
        float pupilMinorAxis;//!<pupil diameter, pupil minor axis value(0-1), the ratio of the pixel value of the minor axis size of the pupil ellipse to the image width, normalization value.
        float pupilMinorAxisMM;//!<pupil diameter, pupil minor axis value(mm).
    };

    struct ETEyeData {
        unsigned int eyeDataExBitMask;//!<eye extend data bit mask, identify the four data below are valid or invalid.
        int blink;//!<blink data, 0-no blink, 1-start blinking, 2-closing process, 3-close eyes, 4-opening process, 5-finish blinking.
        float openness;//!<eye openness(0-100), 0-cloing, 100-opening normally, >100-opening on purpose.
        float eyelidUp;//!<up eyelid data(0-1), up eyelid's vertical position in the image, normalization value, image height is 1.
        float eyelidDown;//!<down eyelid data(0-1), down eyelid's vertical position in the image, normalization value, image height is 1.
    };

    struct ETGazeData {
        unsigned long long timestamp;//!<timestamp.
        int recommend;//!<whether if there has the recommend point. 0-no recommend point, 1-use left eye as recommend point, 2-use right eye as recomment point.
        ETGazePoint recomGaze;//!<recommend gaze data
        ETGazePoint leftGaze;//!<left eye gaze data
        ETGazePoint rightGaze;//!<right eye gaze data

        ETPupilInfo leftPupil;//!<left eye pupil data
        ETPupilInfo rightPupil;//!<right eye pupil data

        ETEyeData leftExData;//!<left eye extend data(include blink and eyelid data)
        ETEyeData rightExData;//!<right eye extend data(include blink and eyelid data)
    };

    typedef struct ETCoefficient {
        unsigned char buf[1024];//!<calibration factor.
    };

    struct NxrCameraImage {
        unsigned char *data;
        uint16_t format;
        uint16_t type;
        uint16_t width;
        uint16_t height;
        uint32_t size;
    };

    struct NxrStreamV4 {
        std::vector<NxrCameraImage> images;
        uint64_t timestamp;
    };

    typedef void (*fn_stream_callback)(StreamType type,NxrStreamData *);
    typedef void (*fn_stereo_callback)(StreamType type,NxrStreamV2 *stream);
    typedef void (*fn_quality_callback)(int);
    typedef void (*fn_status_quality_callback)(int,int);
    typedef void (*fn_percent_callback)(float);
    typedef void (*fn_plane_callback)(NxrPlaneData *);
    typedef void (*fn_detect_tag_callback)(float *rotation,float *translation,uint8_t confidence);
    typedef void (*fn_skeleton_callback)(NxrSkeleton *skeleton);
    typedef void (*fn_gesture_callback)(NxrGesture *gesture);
    typedef void (*fn_pose_callback)(NxrTrackingData *data);
    typedef void (*fn_imu_callback)(NxrRawData *data);
    typedef void (*fn_cnn_raw_callback)(NxrCnnRawData *data);
    typedef void (*fn_cnn_object_callback)(std::vector<NxrCnnObject> object);
    typedef void (*fn_event_callback)(int type,int state);
    typedef void (*fn_mic_callback)(NxrMicData *data);
    typedef void (*fn_map_callback)(std::vector<point> points);
    typedef void (*fn_speaker_callback)();
    typedef void (*fn_stream2_callback)(NxrStreamData *data);
    typedef void (*fn_surface_callback)(std::map<uint64_t,NxrSurface> surfaces);
    typedef void (*fn_gaze_callback)(ETGazeData *data);
    typedef void (*fn_gaze_process_callback)(int index,int percent,void *ctx);
    typedef void (*fn_gaze_finish_callback)(int index,int error,void *ctx);
    typedef void (*fn_stream_callback_v4)(StreamType type,NxrStreamV4 *stream);
    typedef void (*fn_slip_callback)(SLIPData *slip);

};//namespace nxr_client

#endif //NXR_SENSOR_TYPES_H